package com.xinyue.ext.reader.dao;

import java.util.List;

import org.dom4j.Element;

import com.xinyue.ext.Label;
import com.xinyue.ext.data.FinderData;
import com.xinyue.ext.exception.BeanException;
import com.xinyue.ext.exception.FinderException;
import com.xinyue.ext.reader.ParamHolder;
import com.xinyue.ext.type.Type;
import com.xinyue.ext.util.StringUtil;

public abstract class DaoContext implements Label, Type{
	//参数集
	protected static ParamHolder holder;
	
	/**读取查询信息
	 */
	public abstract void read(Element finder) throws FinderException;
	
	/**
	 * 读取公共属性
	 * @param e
	 * @return
	 * @throws BeanException
	 */
	protected FinderData commonRead(Element e) throws FinderException {
		FinderData find = new FinderData();
		
		//是否是查询类型
		if("false".equals(e.attributeValue(query_))) {
			find.setQuery(false);
		}else {
			find.setQuery(true);
		}
		//方法名称
		find.setMethod(methodOprate(e.attributeValue(method_)));
		
		return find;
	}
	
	/**验证方法:方法名称不能为空
	 * 当前验证不支持对方法名相同，参数相同的验证。对字符长度没有限制。
	 */
	private String methodOprate(String method) throws FinderException {
		if(StringUtil.isNull(method)) {
			throw new FinderException("query/hql/sql标签必须定义method属性", holder.getException());
		}
		return method;
	}
	
	
	/**
	 * 验证返回值类型是否正确
	 * @param type
	 * @param flag
	 * @throws FinderException
	 */
	protected void returnType(String type, FinderData find) throws FinderException {
		//基本类型
		if(STRING.equals(type)) {
			find.setConvert(true);
			find.setOnly(true);
		}else if(STRING_S.equals(type)) {
			find.setWarning(true);
		}else if(INTEGER.equals(type)) {
			find.setConvert(true);
			find.setOnly(true);
		}else if(INTEGER_S.equals(type)) {
			find.setWarning(true);
		}else if(LONG_.equals(type)) {
			find.setConvert(true);
			find.setOnly(true);
		}else if(LONG_S.equals(type)) {
			find.setWarning(true);
		}else if(DOUBLE_.equals(type)) {
			find.setConvert(true);
			find.setOnly(true);
		}else if(DOUBLE_S.equals(type)) {
			find.setWarning(true);
		}else if(CHARACTER.equals(type)) {
			find.setConvert(true);
			find.setOnly(true);
		}else if(CHARACTER_S.equals(type)) {
			find.setWarning(true);
		}else if(BYTE_.equals(type)) {
			find.setConvert(true);
			find.setOnly(true);
		}else if(BYTE_S.equals(type)) {
			find.setWarning(true);
		}else if(SHORT_.equals(type)) {
			find.setConvert(true);
			find.setOnly(true);
		}else if(SHORT_S.equals(type)) {
			find.setWarning(true);
		}else if(FLOAT_.equals(type)) {
			find.setConvert(true);
			find.setOnly(true);
		}else if(FLOAT_S.equals(type)) {
			find.setWarning(true);
		}else if(BOOLEAN_.equals(type)) {
			find.setConvert(true);
			find.setOnly(true);
		}else if(BOOLEAN_S.equals(type)) {
			find.setWarning(true);
		}else if(MAP.equals(type)) {
			holder.getDaoImpt().add("java.util.Map");
			type = "Map<String, Object>";
		}else if(OBJ_ARR_S.equals(type)) {//List<Object[]>
			find.setWarning(true);
		}else if(OBJ_ARR.equals(type)) {//Object[]
			find.setConvert(true);
			find.setOnly(true);
		}else if(DATE.equals(type)) {
			holder.getDaoImpt().add("java.util.Date");
			find.setConvert(true);
			find.setOnly(true);
		}else if(DATE_S.equals(type)) {
			holder.getDaoImpt().add("java.util.Date");
			find.setWarning(true);
		}else if(BIGDECIMAL.equals(type)) {
			holder.getDaoImpt().add("java.math.BigDecimal");
			find.setConvert(true);
			find.setOnly(true);
		}else if(BIGDECIMAL_S.equals(type)) {
			holder.getDaoImpt().add("java.math.BigDecimal");
			find.setWarning(true);
		}else if(BLOB.equals(type)) {
			holder.getDaoImpt().add("java.sql.Blob");
			find.setConvert(true);
			find.setOnly(true);
		}else {
			throw new FinderException("hql/sql标签returnType属性值不合法:" + type, holder.getException());
		}
		
		//设置返回值
		find.setReturnType(type);
	}
	
	/**
	 * Java基本类型验证并返回符合hibernate规范的setter语句
	 * @throws FinderException
	 */
	protected String setterHQL(String name, String type) {
		if(DATE.equals(type)) {
			holder.getDaoImpt().add("java.util.Date");
			return "q.setDate(\"" + name + "\", " + name + ");";
		}else if(BIGDECIMAL.equals(type)) {
			holder.getDaoImpt().add("java.math.BigDecimal");
			return "q.setBigDecimal(\"" + name + "\", " + name + ");";
		}else if(STRING.equals(type)) {
			return "q.setString(\"" + name + "\", " + name + ");";
		}else if(BOOLEAN.equals(type)) {
			return "q.setBoolean(\"" + name + "\", " + name + ");";
		}else if(INT.equals(type)) {
			return "q.setInteger(\"" + name + "\", " + name + ");";
		}else if(DOUBLE.equals(type)) {
			return "q.setDouble(\"" + name + "\", " + name + ");";
		}else if(LONG.equals(type)) {
			return "q.setLong(\"" + name + "\", " + name + ");";
		}else if(FLOAT.equals(type)) {
			return "q.setFloat(\"" + name + "\", " + name + ");";
		}else if(BYTE.equals(type)) {
			return "q.setByte(\"" + name + "\", " + name + ");";
		}else if(SHORT.equals(type)) {
			return "q.setShort(\"" + name + "\", " + name + ");";
		}else if(CHAR.equals(type)) {
			return "q.setCharacter(\"" + name + "\", " + name + ");";
		}
		
		return null;
	}
	

	/**
	 * 对SQL语句进行预处理
	 * @throws FinderException 
	 */
	@SuppressWarnings("unchecked")
	protected void processQL(Element state, FinderData find) throws FinderException {
		List<Element> nulls = state.elements(isNotNull_);
		
		/**SQL处理方法
		 * 解析xml，将isNotNull标签下的数据转化成SQL，并替换isNotNull标签内的字符为@+数字
		 */
		if(nulls != null && nulls.size() > 0) {
			//sql字符集处理
			String paramArray = "";
			for (int i = 0; i < nulls.size(); i++) {
				paramArray += "\"" + nulls.get(i).getTextTrim() + "\", \"" + nulls.get(i).attributeValue("key") + "\", ";
				//替换字符集为@+数字
				nulls.get(i).setText("@" + i);
			}
			find.setParamArray(paramArray.substring(0, paramArray.length() - 2));
			
			String reg = state.getStringValue();
			//去除字符集中的制表符、回车，并将前后空格去除，最后将多空格合一。
			String ql = reg.replaceAll("\t|\r|\n", " ").replaceAll("[\\s]+", " ").replaceAll("^[ ]*", "").replaceAll("[ ]*$", "");
			
			find.setState(ql);
			holder.getDaoImptExt().add("commons.DaoUtil");
		}else {
			find.setState(state.getTextTrim());
		}
	}
}
